#region license
// KenEgozi.com - my blog engine
// This project is licensed under the MIT License
//
//Copyright (c) 2007, Ken Egozi
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
#endregion

using System;
using System.Collections.Generic;
using System.Web;
using Castle.Components.DictionaryAdapter;
using Castle.MonoRail.Framework;
using KenEgozi.Com.Domain.Aggregates.Common;
using KenEgozi.Com.Domain.Aggregates.Post;
using KenEgozi.Com.Domain.Repositories;
using KenEgozi.Com.Weblog.Application;
using KenEgozi.Com.Weblog.Helpers;
using KenEgozi.Com.Weblog.Interfaces;
using KenEgozi.Com.Weblog.Services;
using NHibernate.Expression;
using Rhino.Commons;

namespace KenEgozi.Com.Weblog.Controllers
{
	public enum SyndicationType
	{
		Atom
	}

	/// <summary>
	/// Showing the posts
	/// </summary>
	public class PostsController : AbstractController 
	{
		private const string FeedBurnerUrl = "http://feeds.feedburner.com/kenegozi";

		public PostsController(ICachedItemsService CachedItemsService, IDictionaryAdapterFactory dictionaryAdapterFactory) :
			base(CachedItemsService, dictionaryAdapterFactory)
		{
		}

		private IPostsView postsBag;
		protected IPostsView PostsBag
		{
			get
			{
				if (postsBag == null)
					postsBag = DictionaryAdapterFactory.GetAdapter<IPostsView>(PropertyBag);
				return postsBag;
			}
		}

		private IPostView postBag;
		protected IPostView PostBag
		{
			get
			{
				if (postBag == null)
					postBag = DictionaryAdapterFactory.GetAdapter<IPostView>(PropertyBag);
				return postBag;
			}
		}

		/// <summary>
		/// The default view - blog's homepage. showing recent posts
		/// </summary>
		public void List()
		{
			SetLayoutParameters();
			LayoutBag.PageTitle = "Ken Egozi's Blog";
			PostsBag.Posts = Repository.Posts.FindRecent();
		}

		/// <summary>
		/// Old feed endpoint - now redirects to FeedBurner
		/// </summary>
		public void List(SyndicationType syndicationType)
		{
			SimpleLog.Syndication(Context, "Redirected to feedburner");
			Response.StatusCode = 301;
			Redirect(FeedBurnerUrl);
		}

		/// <summary>
		/// End point for FeedBurner
		/// </summary>
		public void Feed()
		{
			CancelLayout();

			Response.ContentType = "application/atom+xml";
			RenderView("\\Syndication\\Atom\\MainFeed");

			List<Post> posts = (List<Post>)Repository.Posts.FindRecent();
			PostsBag.Posts = posts;
			PostsBag.Updated = posts[0].Lifecycle.UpdateDate;
		}

		/// <summary>
		/// Showing "archived" posts - all posts for  given month
		/// </summary>
		/// <param name="year">The year</param>
		/// <param name="month">The month</param>
		public void List(int year, int month)
		{
			SetLayoutParameters();
			DateTime date = new DateTime(year, month, 1);
			LayoutBag.PageTitle = string.Format("Ken Egozi's Blog Archive - {0:MMM yyyy}", date);
			PostsBag.Posts = Repository.Posts.FindInArchive(year, month);
		}


		/// <summary>
		/// Showing all posts for a given tag
		/// </summary>
		/// <param name="tagName">The url friendly name of the tag</param>
		public void ByTag(string tagName)
		{
			SetLayoutParameters();
			LayoutBag.PageTitle = string.Format("{0} at Ken Egozi's Blog", tagName);
			PostsBag.Posts = Repository.Posts.FindByUrlFriendlyTagName(tagName.ToLower());
			RenderView("List");
		}

		/// <summary>
		/// View a single post
		/// </summary>
		/// <param name="permalink">The post's permalink</param>
		public void View(string permalink)
		{
			SetLayoutParameters();

			Post post = Repository.Posts.FindOne(Expression.InsensitiveLike("Permalink", permalink, MatchMode.Exact));

			// maybe it's an old dasBlog permalink?
			if (post == null)
			{
				RedirectionEntry redirection = Repository<RedirectionEntry>.FindOne(Expression.InsensitiveLike("OldPermalink", permalink, MatchMode.Exact));
				if (redirection == null)
					RenderSharedView("/Rescues/NotFound");
				else
				{
					Response.StatusCode = 301;
					Response.Redirect("~/" + redirection.Permalink/*, true*/);
				}
				return;
			}

			PostBag.Post = post;
			LayoutBag.PageTitle = post.Title;
			SimpleExpression statusFilter;
			if (Preferences.AutoApproveComments)
				statusFilter = Expression.Ge("Status", CommentStatus.ProbableOk);
			else
				statusFilter = Expression.Eq("Status", CommentStatus.Approved);
			PostBag.Comments = Repository<Comment>.FindAll(
				Expression.Eq("Post", post), statusFilter);

			// deal with "remember me" tick on the comments entry box
			HttpCookie cookie = Context.UnderlyingContext.Request.Cookies["commenterData"];
			if (cookie != null)
			{
				PostBag.CommenterName = cookie.Values["Name"];
				PostBag.CommenterEmail = cookie.Values["Email"];
				PostBag.CommenterHomepage = cookie.Values["Homepage"];
			}
			PostBag.UseCaptcha = Preferences.UseCaptcha;

			if (Preferences.UseCaptcha)
				StoreNewCaptchaStringInSession();
		}

		public void View(string permalink, SyndicationType syndicationType)
		{
			CancelLayout();
			Response.ContentType = "application/atom+xml";
			RenderView("\\Syndication\\" + syndicationType + "\\CommentsFeed");

			Post post = Repository.Posts.FindOne(Expression.InsensitiveLike("Permalink", permalink, MatchMode.Exact));

			PostBag.Post = post;
			SimpleExpression statusFilter;
			if (Preferences.AutoApproveComments)
				statusFilter = Expression.Ge("Status", CommentStatus.ProbableOk);
			else
				statusFilter = Expression.Eq("Status", CommentStatus.Approved);
			PostBag.Comments = Repository<Comment>.FindAll(Order.Desc("Lifecycle.CreationDate"),
				Expression.Eq("Post", post), statusFilter);

			PostBag.Updated = post.Lifecycle.CreationDate;
			if (post.Comments.Count > 0)
				PostBag.Updated = Collection.First(PostBag.Comments).Lifecycle.UpdateDate;
		}

		private void StoreNewCaptchaStringInSession()
		{
			Session["captcha"] = Guid.NewGuid().ToString("N").Substring(0, 4).ToUpper();
		}
	}
}
